﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Navigant.Infrastructure;
using Navigant.Model.Cases;
using Navigant.Model.Custodians;
using Navigant.Infrastructure.DomainBase;
using System.Collections.Generic;
using System.Configuration;

namespace Navigant.UnitTests
{
    /// <summary>
    ///This is a test class for CustodianServiceTest and is intended
    ///to contain all CustodianServiceTest Unit Tests
    ///</summary>
    [TestClass()]
    public class CustodianServiceTest
    {
        private TestContext testContextInstance;
        private Uri siteUri;
        private IUnitOfWork unitOfWork;

        public CustodianServiceTest()
        {
            this.siteUri = new Uri(ConfigurationManager.AppSettings["testCaseSite"]);
            this.unitOfWork = new UnitOfWork();
        }

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return this.testContextInstance;
            }
            set
            {
                this.testContextInstance = value;
            }
        }

        #region Additional test attributes
        // 
        //You can use the following additional attributes as you write your tests:
        //
        //Use ClassInitialize to run code before running the first test in the class
        //[ClassInitialize()]
        //public static void MyClassInitialize(TestContext testContext)
        //{
        //}
        //
        //Use ClassCleanup to run code after all tests in a class have run
        //[ClassCleanup()]
        //public static void MyClassCleanup()
        //{
        //}
        //
        //Use TestInitialize to run code before running each test
        //[TestInitialize()]
        //public void MyTestInitialize()
        //{
        //}
        //
        //Use TestCleanup to run code after each test has run
        //[TestCleanup()]
        //public void MyTestCleanup()
        //{
        //}
        //
        #endregion


        /// <summary>
        ///A test for GetCustodian
        ///</summary>
        [TestMethod()]
        public void GetCustodianTest()
        {
            int id = this.GetCustodianService().FindAll()[0].Id;
            Custodian custodian = this.GetCustodianBy(id);
            Assert.IsTrue(custodian.Name.FirstName.Length > 0);
        }

        /// <summary>
        ///A test for FindAll
        ///</summary>
        [TestMethod()]
        public void FindAllCustodiansTest()
        {
            IList<Custodian> custodians = this.GetCustodianService().FindAll();
            Assert.IsTrue(custodians.Count > 0);
            this.testContextInstance.WriteLine("{0} custodians found.", custodians.Count);
        }

        /// <summary>
        ///A test for FindAll
        ///</summary>
        [TestMethod()]
        public void GetAllCustodiansPagedTest()
        {
            int itemCount = 0;
            int lastCustodianId = 0;
            IList<Custodian> custodians = this.GetCustodianService().GetAllCustodiansPaged(1, 1, lastCustodianId, out itemCount);
            this.testContextInstance.WriteLine("{0} total custodians.", itemCount);
            Assert.IsTrue(custodians.Count == 1);
            this.testContextInstance.WriteLine("1st page 1st Custodian:  {0}", custodians[0].Id.ToString());
            lastCustodianId = custodians[custodians.Count - 1].Id;
            custodians = this.GetCustodianService().GetAllCustodiansPaged(1, 2, lastCustodianId, out itemCount);
            Assert.IsTrue(custodians.Count == 1);
            this.testContextInstance.WriteLine("2nd page 1st Custodian:  {0}", custodians[0].Id.ToString());
        }

        /// <summary>
        ///A test for saving a new Custodian
        ///</summary>
        [TestMethod()]
        public void AddCustodianTest()
        {
            Custodian newCustodian = this.SaveNewCustodian();
            int newCustodianId = newCustodian.Id;
            Custodian existingCustodian = this.GetCustodianBy(newCustodianId);
            Assert.AreEqual(newCustodian.Id, existingCustodian.Id);
        }

        /// <summary>
        ///A test for saving an existing Custodian
        ///</summary>
        [TestMethod()]
        public void UpdateCustodianTest()
        {
            Custodian custodian = this.SaveNewCustodian();
            int custodianId = custodian.Id;
            custodian.SetExtendedProperty("Is Person", "0");
            this.GetCustodianService().SaveCustodian(custodian);
            this.unitOfWork.Commit();
            Custodian existingCustodian = this.GetCustodianBy(custodianId);
            Assert.AreEqual(false, existingCustodian.IsPerson);
        }

        /// <summary>
        ///A test for removing a Custodian
        ///</summary>
        [TestMethod()]
        public void DeleteCustodianTest()
        {
            this.SaveNewCustodian();
            this.unitOfWork.Commit();
            CustodianService target = this.GetCustodianService();
            int oldCount = target.FindAll().Count;
            this.testContextInstance.WriteLine("Old Count:  {0}", oldCount);
            target.RemoveCustodian(target.FindAll()[0]);
            this.unitOfWork.Commit();
            int newCount = target.FindAll().Count;
            this.testContextInstance.WriteLine("New Count:  {0}", newCount);
            Assert.IsTrue((oldCount - newCount) == 1);
        }

        /// <summary>
        ///A test for getting the extra criteria possible 
        ///values for a particular field of a Custodian
        ///</summary>
        [TestMethod()]
        public void GetExtraCriteriaPossibleValuesTest()
        {
            CustodianService target = this.GetCustodianService();
            IList<string> possibleValues = target.GetExtraCriteriaPossibleValues("Email");
            Assert.IsNotNull(possibleValues);
            if (possibleValues.Count > 0)
            {
                this.testContextInstance.WriteLine("Possible Values:");
                foreach (string value in possibleValues)
                {
                    this.testContextInstance.WriteLine(value);
                }
            }
        }

        private Custodian GetCustodianBy(int id)
        {
            CustodianService service = new CustodianService(CaseService.GetCaseBy(this.siteUri));
            return service.GetCustodian(id);
        }

        private CustodianService GetCustodianService()
        {
            Case currentCase = CaseService.GetCaseBy(this.siteUri);
            return new CustodianService(currentCase, this.unitOfWork);
        }

        private Custodian SaveNewCustodian()
        {
            CustodianService service = this.GetCustodianService();
            Custodian custodian = new Custodian(CaseService.GetCaseBy(this.siteUri), new CustodianName("Timothy McCarthy"), "tmccart1@san.rr.com");
            service.SaveCustodian(custodian);
            this.unitOfWork.Commit();
            return custodian;
        }
    }
}
